/*
 * ﻿Copyright (C) 2011-2013 NewMain Softech
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package com.newmainsoftech.aspectjutil.eventmanager;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import junit.framework.Assert;
import junit.framework.TestCase;

import org.junit.Before;
import org.slf4j.Logger;

import com.newmainsoftech.aspectjutil.eventmanager.TestAspect.LoggerAccessorIntf;

/**
 * Abstract template of test class what sets up class loader and event tracing capability. 
 * The following information regarding event will be traced: 
 * <ul>
 * <li>event</li>
 * <li>eventer</li>
 * <li>event result</li>
 * </ul>
 * 
 * @author <a href="mailto:artymt@gmail.com">Arata Y.</a>
 */
abstract public class EventHandlerTestTemplate extends TestCase implements LoggerAccessorIntf {
	protected static Logger logger;
		@Override
		public Logger getLogger() {
			return EventHandlerTestTemplate.logger;
		}

	protected ClassLoader childDelegationClassLoader;
	protected List<String> eventTraceList;
	protected List<Object> eventerTraceList;
	protected List<Object> eventResultTraceList;
	protected List<Class<?>> triggeredEventTraceList;
	
	@Before
	public void setUp() {
		// Initialize childDelegationClassLoader --------------------------------------------------
		try {
			childDelegationClassLoader = EventManagerTestUtils.childDelegationClassLoaderFactory();
		}
		catch( Throwable throwable) {
			String message = "Failure in initializing childDelegationClassLoader.";
			if ( logger.isErrorEnabled()) {
				logger.error( message, throwable);
			}
			Assert.fail( message + "\nCheck error log for detail.");
		}
		
		ClassLoader currentClassLoader = this.getClass().getClassLoader();
		if ( currentClassLoader != childDelegationClassLoader.getParent()) {
			// childDelegationClassLoader needs to be child of current class loader in order for  
			// other classes than classes and test-classes of aspectjutil-eventmanager module to be loaded. 
			String message = "Current class loader is NOT parent of childDelegationClassLoader.";
			ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
			if ( systemClassLoader != childDelegationClassLoader.getParent()) {
				message 
				= message + " System class loader is NOT parent of childDelegationClassLoader either.";
			}
			else {
				message 
				= message + " System class loader is parent of childDelegationClassLoader.";
			}
			if ( logger.isErrorEnabled()) {
				logger.error( message);
			}
			Assert.fail( message);
		}
		// ----------------------------------------------------------------------------------------
		
		Class<?> eventTraceSupporterClass = null;
		try {
			eventTraceSupporterClass 
			= EventManagerTestUtils.getEventTraceSupporterClass( childDelegationClassLoader);
		}
		catch( Throwable throwable) {
			String message = 
				String.format(
						"Failure in obtaining %1$s class.",
						EventManagerTestUtils.EventTraceSupporterClassName
						);
			if ( logger.isErrorEnabled()) {
				logger.error( message, throwable);
			}
			Assert.fail( message + "\nCheck error log for detail.");
		}
		
		// Initialize eventTraceList --------------------------------------------------------------
		eventTraceList = Collections.synchronizedList( new LinkedList<String>());
		try {
			EventManagerTestUtils.setEventTraceListOfEventTraceSupporter( 
					eventTraceSupporterClass, eventTraceList);
		}
		catch( Throwable throwable) {
			String message = 
				String.format(
						"Failure in initializing %1$s.eventTraceList member field.",
						EventManagerTestUtils.EventTraceSupporterClassName
						);
			if ( logger.isErrorEnabled()) {
				logger.error( message, throwable);
			}
			throw new RuntimeException( message + "\nCheck error log for detail.");
		}
		// ----------------------------------------------------------------------------------------
		
		// Initialize eventerTraceList ------------------------------------------------------------
		eventerTraceList = Collections.synchronizedList( new LinkedList<Object>());
		try {
			EventManagerTestUtils.setEventerTraceListOfEventTraceSupporter( 
					eventTraceSupporterClass, eventerTraceList);
		}
		catch( Throwable throwable) {
			String message = 
				String.format(
						"Failure in initializing %1$s.eventerTraceList member field.",
						EventManagerTestUtils.EventTraceSupporterClassName
						);
			if ( logger.isErrorEnabled()) {
				logger.error( message, throwable);
			}
			throw new RuntimeException( message + "\nCheck error log for detail.");
		}
		// ----------------------------------------------------------------------------------------
		
		// Initialize eventResultTraceList ------------------------------------------------------------
		eventResultTraceList = Collections.synchronizedList( new LinkedList<Object>());
		try {
			EventManagerTestUtils.setEventResultTraceListOfEventTraceSupporter( 
					eventTraceSupporterClass, eventResultTraceList);
		}
		catch( Throwable throwable) {
			String message = 
				String.format(
						"Failure in initializing %1$s.eventResultTraceList member field.",
						EventManagerTestUtils.EventTraceSupporterClassName
						);
			if ( logger.isErrorEnabled()) {
				logger.error( message, throwable);
			}
			throw new RuntimeException( message + "\nCheck error log for detail.");
		}
		// ----------------------------------------------------------------------------------------
		
		// Initialize triggeredEventTraceList -----------------------------------------------------
		triggeredEventTraceList = Collections.synchronizedList( new LinkedList<Class<?>>());
		try {
			EventManagerTestUtils.setTriggeredEventTraceListOfEventTraceSupporter( 
					eventTraceSupporterClass, triggeredEventTraceList);
		}
		catch( Throwable throwable) {
			String message = 
				String.format(
						"Failure in initializing %1$s.triggeredEventTraceList member field.",
						EventManagerTestUtils.EventTraceSupporterClassName
						);
			if ( logger.isErrorEnabled()) {
				logger.error( message, throwable);
			}
			throw new RuntimeException( message + "\nCheck error log for detail.");
		}
		// ----------------------------------------------------------------------------------------
	}
}
